package com.schedualnew.mq.util;

import com.schedualnew.mq.dto.esb.notice.WechatNoticeResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.stereotype.Component;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import java.io.*;

@Component
public class MarshallerUtils {
    private Logger log = LoggerFactory.getLogger(MarshallerUtils.class);

    private String xmlCoding = "UTF-8";

    @Autowired
    private Jaxb2Marshaller marshaller;


    public <T> T xmlToObject(String xml, Class<T> requiredType) {
        try {
            Source source = new StreamSource(new StringReader(xml));
            //createMarshallerByType(requiredType);
            T obj = (T) marshaller.unmarshal(source);
            return obj;
        } catch (Exception e) {
            throw new RuntimeException(String.format("xml解析失败", new Object[]{xml}), e);
        }
    }


    public Object toBeanFromFile(String absPath, String fileName, Class type) throws Exception {
        String filePath = absPath + fileName;
        InputStream ins = null;
        try {
            ins = new FileInputStream(new File(filePath));
        } catch (Exception e) {
            throw new Exception("读{" + filePath + "}文件失败！", e);
        }
        Object obj = null;
        try {
            Unmarshaller unMar = createUnMarshallerByType(type);
            obj = unMar.unmarshal(ins);
        } catch (Exception e) {
            throw new Exception("解析{" + filePath + "}文件失败！", e);
        }
        if (ins != null)
            ins.close();
        return obj;
    }

    private Marshaller createMarshallerByType(Class type) {
        Marshaller mar = null;
        try {
            JAXBContext jax = JAXBContext.newInstance(new Class[]{type});
            mar = jax.createMarshaller();
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();
        }
        return mar;
    }

    private Unmarshaller createUnMarshallerByType(Class type) {
        Unmarshaller unMar = null;
        try {
            JAXBContext jax = JAXBContext.newInstance(new Class[]{type});
            unMar = jax.createUnmarshaller();
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();
        }
        return unMar;
    }


    public String parseObjectXmlData(Object obj) {
        String backXml = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Marshaller mar = createMarshallerByType(obj.getClass());
            mar.marshal(obj, baos);
            backXml = baos.toString();
            backXml = new String(baos.toByteArray(), xmlCoding);
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();
        }
        return backXml;
    }


    public String parseObjectXmlData(Object obj, String enCoding) {
        String backXml = null;
        try {
            if (enCoding != null)
                xmlCoding = enCoding;
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Marshaller mar = createMarshallerByType(obj.getClass());
            mar.marshal(obj, baos);
            backXml = baos.toString();
            backXml = new String(baos.toByteArray(), xmlCoding);
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();
        }
        return backXml;
    }


    public Object parseXmlDataObject(Class type, String xmlData) {
        if (xmlData == null || xmlData.trim().length() == 0)
            return null;
        try {
            Unmarshaller unMar = createUnMarshallerByType(type);
            ByteArrayInputStream bais = new ByteArrayInputStream(xmlData.getBytes(xmlCoding));
            return unMar.unmarshal(bais);
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    public Object parseXmlDataObject(Class type, String xmlData, String enCoding) {
        if (xmlData == null || xmlData.trim().length() == 0)
            return null;
        try {
            xmlCoding = enCoding;
            Unmarshaller unMar = createUnMarshallerByType(type);

            ByteArrayInputStream bais = new ByteArrayInputStream(xmlData.getBytes(xmlCoding));
            return unMar.unmarshal(bais);
        } catch (Exception e) {
            log.error("xml处理失败:" + e.getMessage());
            e.printStackTrace();

            return null;
        }
    }

    public static void main(String[] args) throws JAXBException, ParserConfigurationException, SAXException {
        String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
                "<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'>\n" +
                "    <SOAP-ENV:Body>\n" +
                "        <SendNoticeResponse xmlns=\"http://www.dhcc.com.cn/emr/interfaceservice\">\n" +
                "            <SendNoticeResult>0</SendNoticeResult>\n" +
                "        </SendNoticeResponse>\n" +
                "    </SOAP-ENV:Body>\n" +
                "</SOAP-ENV:Envelope>";

        JAXBContext context = JAXBContext.newInstance(WechatNoticeResponse.class);
        StringReader reader = new StringReader(xmlStr);
        SAXParserFactory sax = SAXParserFactory.newInstance();
        sax.setNamespaceAware(false); // 忽略命名空间
        XMLReader xmlReader = sax.newSAXParser().getXMLReader();
        Source source = new SAXSource(xmlReader, new InputSource(reader));
        Unmarshaller unmarshaller = context.createUnmarshaller();
        WechatNoticeResponse obj = (WechatNoticeResponse) unmarshaller.unmarshal(source);
        System.out.println(obj);
//        JAXBContext jaxbContext = JAXBContext.newInstance(WechatNoticeResponse.class);
//        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
//        StringReader reader = new StringReader(xmlStr);
//        WechatNoticeResponse message = (WechatNoticeResponse) unmarshaller.unmarshal(reader);
//        System.out.println(message);
        //WechatNoticeResponse response = marshallerUtils.xmlToObject(xmlStr, WechatNoticeResponse.class);
        //log.info(JSONUtil.toJsonStr(response));

    }
}
